package game.module.nn.logic;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import game.module.nn.NnConstants;

public class NnAlgorithm {

	private static Logger logger = LoggerFactory.getLogger(NnAlgorithm.class);

	static class SingletonHolder {
		static NnAlgorithm instance = new NnAlgorithm();
	}

	public static NnAlgorithm getInstance() {
		return SingletonHolder.instance;
	}

	public byte GetCardType(byte[] cbCardData, byte cbCardCount) {
		assert(cbCardCount==NnConstants.MAX_COUNT);

		//炸弹牌型
		byte bSameCount = 0;
		SortCardList(cbCardData,cbCardCount);
		byte bSecondValue = GetCardValue(cbCardData[cbCardCount/2]);
		for(byte i=0;i<cbCardCount;i++)
		{
			if(bSecondValue == GetCardValue(cbCardData[i]))
			{
				bSameCount++;
			}
		}
		if(bSameCount==4)return NnConstants.OX_FOUR_SAME;

		//五小牛 5张牌均小于5，且总和小于10
		boolean allMin5 = true;
		int sumVal = 0;
		for(byte i=0;i<cbCardCount;i++)
		{
			byte cardVal = GetCardValue(cbCardData[i]);
			sumVal+=cardVal;
			if(cardVal >= 5)
			{
				allMin5 = false;
				break;
			}
		}
		if(allMin5 && sumVal < 10) {
			return NnConstants.OX_WU_XIAO;
		}
		
		byte bKingCount=0,bTenCount=0;
		for(byte i=0;i<cbCardCount;i++)
		{
			if(GetCardValue(cbCardData[i])>10)
			{
				bKingCount++;
			}
			else if(GetCardValue(cbCardData[i])==10)
			{
				bTenCount++;
			}
		}
		if(bKingCount==NnConstants.MAX_COUNT) return NnConstants.OX_FIVEKING;
		else if(bKingCount==NnConstants.MAX_COUNT-1 && bTenCount==1) return NnConstants.OX_FOURKING;

		////葫芦牌型
		//if(bSameCount==3)
		//{
		//	if((bSecondValue!=GetCardValue(cbCardData[3]) && GetCardValue(cbCardData[3])==GetCardValue(cbCardData[4]))
		//	||(bSecondValue!=GetCardValue(cbCardData[1]) && GetCardValue(cbCardData[1])==GetCardValue(cbCardData[0])))
		//		return OX_THREE_SAME;
		//}

		byte[] bTemp = new byte[NnConstants.MAX_COUNT];
		byte bSum=0;
		for (byte i=0;i<cbCardCount;i++)
		{
			bTemp[i]=GetCardLogicValue(cbCardData[i]);
			bSum+=bTemp[i];
		}

		for (byte i=0;i<cbCardCount-1;i++)
		{
			for (byte j=(byte)(i+1);j<cbCardCount;j++)
			{
				if((bSum-bTemp[i]-bTemp[j])%10==0)
				{
					return (byte)(((bTemp[i]+bTemp[j])>10)?(bTemp[i]+bTemp[j]-10):(bTemp[i]+bTemp[j]));
				}
			}
		}

		return NnConstants.OX_VALUE0;
	}
	
	//获取倍数
	public byte GetTimes(byte cbCardData[], byte cbCardCount)
	{
		if(cbCardCount!=NnConstants.MAX_COUNT)return 0;

		byte bTimes=GetCardType(cbCardData,NnConstants.MAX_COUNT);
		if(bTimes<7)return 1;
		else if(bTimes==7)return 2;
		else if(bTimes==8)return 2;
		else if(bTimes==9)return 2;
		else if(bTimes==10)return 3;
		else if(bTimes==NnConstants.OX_THREE_SAME)return 5;
		else if(bTimes==NnConstants.OX_FOUR_SAME)return 5;
		else if(bTimes==NnConstants.OX_FOURKING)return 5;
		else if(bTimes==NnConstants.OX_FIVEKING)return 5;
		else if(bTimes==NnConstants.OX_WU_XIAO)return 5;

		return 0;
	}

	//获取牛牛
	public boolean GetOxCard(byte cbCardData[], byte cbCardCount)
	{
		assert(cbCardCount==NnConstants.MAX_COUNT);

		//设置变量
		byte[] bTemp = new byte[NnConstants.MAX_COUNT],bTempData = new byte[NnConstants.MAX_COUNT];
		bTempData = Arrays.copyOf(cbCardData, bTempData.length);
		byte bSum=0;
		for (byte i=0;i<cbCardCount;i++)
		{
			bTemp[i]=GetCardLogicValue(cbCardData[i]);
			bSum+=bTemp[i];
		}

		//查找牛牛
		for (byte i=0;i<cbCardCount-1;i++)
		{
			for (byte j=(byte)(i+1);j<cbCardCount;j++)
			{
				if((bSum-bTemp[i]-bTemp[j])%10==0)
				{
					byte bCount=0;
					for (byte k=0;k<cbCardCount;k++)
					{
						if(k!=i && k!=j)
						{
							cbCardData[bCount++] = bTempData[k];
						}
					}
					assert(bCount==3);

					cbCardData[bCount++] = bTempData[i];
					cbCardData[bCount++] = bTempData[j];

					return true;
				}
			}
		}
		byte cardType = GetCardType(cbCardData, NnConstants.MAX_COUNT);
		if (cardType == NnConstants.OX_THREE_SAME || cardType == NnConstants.OX_FOUR_SAME
				|| cardType == NnConstants.OX_FOURKING || cardType == NnConstants.OX_FIVEKING
				|| cardType == NnConstants.OX_WU_XIAO) {
			return true;
		}
		return false;
	}

	//获取整数
	public boolean IsIntValue(byte cbCardData[], byte cbCardCount)
	{
		byte sum=0;
		for(byte i=0;i<cbCardCount;i++)
		{
			sum+=GetCardLogicValue(cbCardData[i]);
		}
		assert(sum>0);
		return (sum%10==0);
	}
	
	//排列扑克
	public void SortCardList(byte cbCardData[], byte cbCardCount)
	{
		//转换数值
		byte[] cbLogicValue = new byte[NnConstants.MAX_COUNT];
		for (byte i=0;i<cbCardCount;i++) cbLogicValue[i]=GetCardValue(cbCardData[i]);	

		//排序操作
		boolean bSorted=true;
		byte cbTempData,bLast=(byte)(cbCardCount-1);
		do
		{
			bSorted=true;
			for (byte i=0;i<bLast;i++)
			{
				if ((cbLogicValue[i]<cbLogicValue[i+1])||
					((cbLogicValue[i]==cbLogicValue[i+1])&&(cbCardData[i]<cbCardData[i+1])))
				{
					//交换位置
					cbTempData=cbCardData[i];
					cbCardData[i]=cbCardData[i+1];
					cbCardData[i+1]=cbTempData;
					cbTempData=cbLogicValue[i];
					cbLogicValue[i]=cbLogicValue[i+1];
					cbLogicValue[i+1]=cbTempData;
					bSorted=false;
				}	
			}
			bLast--;
		} while(bSorted==false);

		return;
	}
	
	//对比扑克
	public boolean CompareCard(byte cbFirstData[], byte cbNextData[], byte cbCardCount,boolean FirstOX,boolean NextOX)
	{
		if(FirstOX!=NextOX)return FirstOX;

		//比较牛大小
		if(FirstOX==true)
		{
			//获取点数
			byte cbNextType=GetCardType(cbNextData,cbCardCount);
			byte cbFirstType=GetCardType(cbFirstData,cbCardCount);

			//点数判断
			if (cbFirstType!=cbNextType) return (cbFirstType>cbNextType);

			switch(cbNextType)
			{
			case NnConstants.OX_FOUR_SAME:		//炸弹牌型	
			case NnConstants.OX_THREE_SAME:		//葫芦牌型
				{
					//排序大小
					byte[] bFirstTemp = new byte[NnConstants.MAX_COUNT],bNextTemp = new byte[NnConstants.MAX_COUNT];
					bFirstTemp = Arrays.copyOf(cbFirstData, cbCardCount);
					bNextTemp = Arrays.copyOf(cbNextData, cbCardCount);
					SortCardList(bFirstTemp,cbCardCount);
					SortCardList(bNextTemp,cbCardCount);

					return GetCardValue(bFirstTemp[NnConstants.MAX_COUNT/2])>GetCardValue(bNextTemp[NnConstants.MAX_COUNT/2]);
				}
			}
		}

		//排序大小
		byte[] bFirstTemp = new byte[NnConstants.MAX_COUNT],bNextTemp = new byte[NnConstants.MAX_COUNT];
		bFirstTemp = Arrays.copyOf(cbFirstData, cbCardCount);
		bNextTemp = Arrays.copyOf(cbNextData, cbCardCount);
		SortCardList(bFirstTemp,cbCardCount);
		SortCardList(bNextTemp,cbCardCount);

		//比较数值
		byte cbNextMaxValue=GetCardValue(bNextTemp[0]);
		byte cbFirstMaxValue=GetCardValue(bFirstTemp[0]);
		if(cbNextMaxValue!=cbFirstMaxValue)return cbFirstMaxValue>cbNextMaxValue;

		//比较颜色
		return GetCardColor(bFirstTemp[0]) > GetCardColor(bNextTemp[0]);
	}

	// 逻辑数值
	public byte GetCardLogicValue(byte cbCardData) {
		// 扑克属性
		byte bCardColor = GetCardColor(cbCardData);
		byte bCardValue = GetCardValue(cbCardData);

		//转换数值
		return (bCardValue>10)?(10):bCardValue;
	}

	// 获取数值
	public byte GetCardValue(byte cbCardData) {
		return (byte) (cbCardData & NnConstants.LOGIC_MASK_VALUE);
	}

	// 获取花色
	public byte GetCardColor(byte cbCardData) {
		return (byte) (cbCardData & NnConstants.LOGIC_MASK_COLOR);
	}

	public static void main(String[] args) {
		NnAlgorithm ddzAlgorithm = new NnAlgorithm();
		// byte cardType = ddzAlgorithm.GetCardType(new byte[] { 0x08, 0x18,
		// 0x27, 0x37, 0x16, 0x26 }, (byte) 6);
		// System.out.println(cardType);
//		byte[] toSortList = new byte[] { 0x34, 0x25, 0x0A, 0x18 };
//		ddzAlgorithm.SortCardList(toSortList, (byte) toSortList.length, DdzConstants.ST_ORDER);
//		logger.info("a={}",toSortList);
	}

}
